<template>
  <q-dialog :model-value="modelValue" @update:model-value="handleDialogUpdate">
    <q-card style="width: 500px">
      <q-card-section>
        <div class="text-h6">{{ title }}</div>
      </q-card-section>

      <q-card-section class="q-pt-none">
        <q-form @submit="submitDataScope">
          <q-input v-model="form.name" label="角色名称" readonly outlined dense class="q-mb-sm" />

          <q-input v-model="form.key" label="权限字符" readonly outlined dense class="q-mb-sm" />

          <q-select
            v-model="form.data_scope"
            :options="dataScopeOptions"
            label="权限范围"
            outlined
            dense
            emit-value
            map-options
            @update:model-value="handleDataScopeChange"
            class="q-mb-sm"
          />

          <template v-if="showDeptTree">
            <div class="row q-mb-sm q-gutter-sm">
              <q-checkbox
                v-model="deptExpand"
                label="展开/折叠"
                @update:model-value="handleExpandAll"
              />
              <q-checkbox
                v-model="deptNodeAll"
                label="全选/全不选"
                @update:model-value="handleSelectAll"
              />
              <q-checkbox v-model="form.dept_check_strictly" label="父子联动" />
            </div>

            <q-tree
              ref="deptTreeRef"
              :nodes="deptOptions"
              node-key="id"
              label-key="label"
              v-model:selected="selectedNodes"
              v-model:expanded="expandedNodes"
              :tick-strategy="tickStrategy"
              :no-connectors="true"
              :no-nodes-label="loadingLabel"
              class="tree-border"
              style="max-height: 300px; overflow-y: auto"
            />
          </template>
        </q-form>
      </q-card-section>

      <q-card-actions align="right">
        <q-btn flat label="取消" color="primary" @click="cancelDataScope" />
        <q-btn label="确定" type="submit" color="primary" @click.prevent="submitDataScope" />
      </q-card-actions>
    </q-card>
  </q-dialog>
</template>

<script setup>
import { getRole, updateRole } from '@/api/sys/role'
import { roleDeptTreeselect } from '@/api/sys/role'

const props = defineProps({
  modelValue: {
    type: Boolean,
    default: false,
  },
  title: {
    type: String,
    default: '分配数据权限',
  },
  dataScopeOptions: {
    type: Array,
    default: () => [
      { value: 0, label: '仅本人数据权限' },
      { value: 1, label: '本部门及以下数据权限' },
      { value: 2, label: '本部门数据权限' },
      { value: 3, label: '全部数据权限' },
      { value: 4, label: '自定数据权限' },
    ],
  },
})

const emit = defineEmits(['update:modelValue', 'success', 'cancel'])

// Refs
const deptExpand = ref(false)
const deptNodeAll = ref(false)
const deptOptions = ref([])
const deptTreeRef = ref(null)
const expandedNodes = ref([])
const selectedNodes = ref([])
const loadingLabel = ref('加载中，请稍候')

// Form data
const form = ref({
  id: undefined,
  name: undefined,
  key: undefined,
  data_scope: undefined,
  dept: [],
  dept_check_strictly: true,
})

// Computed
const showDeptTree = computed(() => form.value.data_scope === 4)
const tickStrategy = computed(() => (form.value.dept_check_strictly ? 'leaf' : 'strict'))

// Watchers
watch(
  () => form.value.dept_check_strictly,
  (newVal) => {
    if (deptTreeRef.value) {
      deptTreeRef.value.setTickStrategy(newVal ? 'leaf' : 'strict')
    }
  },
)

// Methods
const handleDialogUpdate = (value) => {
  emit('update:modelValue', value)
}

const handleExpandAll = (expand) => {
  if (!deptTreeRef.value) return

  expandedNodes.value = expand
    ? [...new Set([...expandedNodes.value, ...getAllNodeIds(deptOptions.value)])]
    : []
}

const handleSelectAll = (selectAll) => {
  if (!deptTreeRef.value) return

  selectedNodes.value = selectAll
    ? [...new Set([...selectedNodes.value, ...getRelevantNodeIds()])]
    : []
}

const getRelevantNodeIds = () => {
  return form.value.dept_check_strictly
    ? getAllLeafNodeIds(deptOptions.value)
    : getAllNodeIds(deptOptions.value)
}

const getAllNodeIds = (nodes) => {
  return nodes.reduce((ids, node) => {
    ids.push(node.id)
    if (node.children?.length) {
      ids.push(...getAllNodeIds(node.children))
    }
    return ids
  }, [])
}

const getAllLeafNodeIds = (nodes) => {
  return nodes.reduce((ids, node) => {
    if (!node.children?.length) {
      ids.push(node.id)
    } else {
      ids.push(...getAllLeafNodeIds(node.children))
    }
    return ids
  }, [])
}

const handleDataScopeChange = (value) => {
  if (value !== 4) {
    selectedNodes.value = []
  }
}

const handleDataScope = async (row) => {
  reset()
  const id = row.id

  try {
    const [roleResponse, deptResponse] = await Promise.all([getRole(id), roleDeptTreeselect(id)])

    form.value = {
      ...roleResponse.data,
      sort: Number(roleResponse.data.sort),
      dept_check_strictly: roleResponse.data.dept_check_strictly !== false,
    }

    deptOptions.value = deptResponse.data[0]?.depts || []
    selectedNodes.value = deptResponse.data[0]?.dept || []
    expandedNodes.value = getDefaultExpandedNodes(deptOptions.value, 2)
    deptExpand.value = expandedNodes.value.length > 0

    emit('update:modelValue', true)
  } catch (error) {
    console.error(' 获取数据权限失败:', error)
    loadingLabel.value = '加载失败，请重试'
  }
}

const getDefaultExpandedNodes = (nodes, maxLevel, currentLevel = 1) => {
  if (currentLevel > maxLevel) return []

  return nodes.reduce((ids, node) => {
    ids.push(node.id)
    if (node.children?.length) {
      ids.push(...getDefaultExpandedNodes(node.children, maxLevel, currentLevel + 1))
    }
    return ids
  }, [])
}

const submitDataScope = async () => {
  if (!form.value.id) return

  try {
    form.value.dept = selectedNodes.value
    await updateRole(form.value)
    emit('success')
    emit('update:modelValue', false)
  } catch (error) {
    console.error(' 更新数据权限失败:', error)
  }
}

const cancelDataScope = () => {
  emit('cancel')
  emit('update:modelValue', false)
  reset()
}

const reset = () => {
  form.value = {
    id: undefined,
    name: undefined,
    key: undefined,
    data_scope: undefined,
    dept: [],
    dept_check_strictly: true,
  }
  selectedNodes.value = []
  expandedNodes.value = []
  deptExpand.value = false
  deptNodeAll.value = false
  deptOptions.value = []
  loadingLabel.value = '加载中，请稍候'
}

defineExpose({
  handleDataScope,
})
</script>
